package com.lgrousset.loanssimulator.shared.model;

import java.util.ArrayList;
import java.util.List;

public class Loan {
	private Double amount;
	private Integer duration;
	private Double rate;
	private Double insuranceRate;
	
	public Loan(Double amount, Integer duration, Double rate, Double insuranceRate) {
		super();
		this.amount = amount;
		this.duration = duration;
		this.rate = rate;
		this.insuranceRate = insuranceRate;
	}

	public class Schedule{
		private String label;
		private Double returnedAmount;
		private Double interestAmount;
		private Double insuranceAmount;
		
		public Schedule(String label, Double returnedAmount, Double interestAmount, Double insuranceAmount) {
			super();
			this.label = label;
			this.returnedAmount = returnedAmount;
			this.interestAmount = interestAmount;
			this.insuranceAmount = insuranceAmount;
		}

		/**
		 * @return the label
		 */
		public String getLabel() {
			return label;
		}
		/**
		 * @param label the label to set
		 */
		public void setLabel(String label) {
			this.label = label;
		}
		/**
		 * @return the outstandingAmount
		 */
		public Double getReturnedAmount() {
			return returnedAmount;
		}
		/**
		 * @param outstandingAmount the outstandingAmount to set
		 */
		public void setReturnedAmount(Double returnedAmount) {
			this.returnedAmount = returnedAmount;
		}
		/**
		 * @return the interestAmount
		 */
		public Double getInterestAmount() {
			return interestAmount;
		}
		/**
		 * @param interestAmount the interestAmount to set
		 */
		public void setInterestAmount(Double interestAmount) {
			this.interestAmount = interestAmount;
		}
		/**
		 * @return the insuranceAmount
		 */
		public Double getInsuranceAmount() {
			return insuranceAmount;
		}
		/**
		 * @param insuranceAmount the insuranceAmount to set
		 */
		public void setInsuranceAmount(Double insuranceAmount) {
			this.insuranceAmount = insuranceAmount;
		}
	}
	
	/**
	 * @return the amount
	 */
	public Double getAmount() {
		return amount;
	}
	/**
	 * @param amount the amount to set
	 */
	public void setAmount(Double amount) {
		this.amount = amount;
	}
	/**
	 * @return the duration
	 */
	public Integer getDuration() {
		return duration;
	}
	/**
	 * @param duration the duration to set
	 */
	public void setDuration(Integer duration) {
		this.duration = duration;
	}
	/**
	 * @return the rate
	 */
	public Double getRate() {
		return rate;
	}
	/**
	 * @param rate the rate to set
	 */
	public void setRate(Double rate) {
		this.rate = rate;
	}
	/**
	 * @return the insuranceRate
	 */
	public Double getInsuranceRate() {
		return insuranceRate;
	}
	/**
	 * @param insuranceRate the insuranceRate to set
	 */
	public void setInsuranceRate(Double insuranceRate) {
		this.insuranceRate = insuranceRate;
	}
	
	public Integer getDurationInMonth() {
		return duration*12;
	}
	
	private Double getPeriodicRate(){
		return getRate()/12;
	}
	
	public Double getMonthly(){
		return (getAmount()*getPeriodicRate()/100)/(1-Math.pow((1+getPeriodicRate()/100),-getDurationInMonth()));
	}
	
	public Double getInsurance(){
		return getAmount()*getInsuranceRate()/100/12;
	}
	
	public List<Schedule> getAmortizationSchedule(){
		List<Schedule> list = new ArrayList<Loan.Schedule>();
		
		Double outstanding = getAmount();
		Double insuranceAmount = getInsurance();
		
		Double interestAmountYear = 0.0;
		Double returnedAmountYear = 0.0;
		Double insuranceAmountYear = 0.0;
		
		for(int month = 1; month <= getDurationInMonth(); month++){
			Double interests = outstanding * getPeriodicRate() / 100;
			Double returned = getMonthly() - interests;
			
			interestAmountYear += interests;
			returnedAmountYear += returned;
			insuranceAmountYear += insuranceAmount;
			
			outstanding -= returned;

			if(month%12 == 0){
				list.add(new Schedule("Année "+String.valueOf((month/12)), returnedAmountYear, interestAmountYear, insuranceAmountYear));
				interestAmountYear = 0.0;
				returnedAmountYear = 0.0;
				insuranceAmountYear = 0.0;
			}
			
			
		}
		return list;
	}
}
